home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / filesyst / umsdos / umsdos-0.000 / umsdos-0.5.doc.txt
Text File  |  1994-12-16  |  69KB  |  1,914 lines

  1.  
  2.  
  3.     1        Specification of the Umsdos file system for LINUX                 1
  4.     2        What is UMSDOS                                                    1
  5.     3        General strategy                                                  1
  6.     4        File name mangling                                                1
  7.     5        --linux-.---: the EMD file                                        4
  8.     6        Hard links                                                        6
  9.     7        Symbolic links                                                    7
  10.     8        Special file                                                      7
  11.     9        Pseudo root                                                       8
  12.     10       Dual mode                                                        10
  13.     11       Miscellaneous                                                    11
  14.     11.1     UMSDOS_create                                                    11
  15.     11.2     UMSDOS_ioctl_dir                                                 12
  16.     11.3     UMSDOS_lookup                                                    14
  17.     11.4     UMSDOS_notify_change                                             15
  18.     11.5     UMSDOS_readdir                                                   16
  19.     11.6     mount and UMSDOS_remount_fs                                      16
  20.     11.7     UMSDOS_rename                                                    17
  21.     11.8     Data structure                                                   18
  22.     11.9     Inode management                                                 18
  23.     12       Synchronisation problems                                         18
  24.     13       Convention and style                                             19
  25.     14       Weakness and features                                            21
  26.     15       utilities                                                        22
  27.     15.1     The UMSDOS synchroniser                                          22
  28.     15.2     Other                                                            24
  29.     16       Test cases                                                       25
  30.     16.1     utstgen                                                          25
  31.     16.2     utstspc                                                          27
  32.  
  33.  
  34.                                                              1
  35.  
  36.  
  37.     17       The MsDOS fs                                                     30
  38.  
  39.  
  40.     1        Specification of the Umsdos file system for LINUX           
  41.     
  42.     This document describe the implementation of the UMSDOS file 
  43.     system for LINUX. It contains mostly implementation notes 
  44.     rather than a formal description of the concept. It is 
  45.     intended for a reader who already has a good knowledge of 
  46.     the LINUX VFS system. It is expected (hope) that such a 
  47.     person may find weakness (or bugs) in UMSDOS just by reading 
  48.     this document. It is the first document to read if you 
  49.     suspect a bug.
  50.     
  51.     2        What is UMSDOS                                              
  52.     
  53.     UMSDOS stand for "Unix in MSDOS" file system. UMSDOS is a 
  54.     full feature unixlike file system for LINUX. It operates 
  55.     within the limits (and semantics) of a normal MSDOS FAT file 
  56.     system. chkdsk won't complain at all. No dirty tricks. 
  57.     UMSDOS DOES not use MSDOS (the OS) to run. In case anyone 
  58.     wonder. Using a special file in each directory 
  59.     ("--linux-.---"), UMSDOS simulate the full UNIX semantic (I 
  60.     hope :-) ):
  61.     
  62.             Long file name
  63.             case sensitive
  64.             free format file name like "This.is.a.sample"
  65.         Permissions and owner (user and group)
  66.         Links (hard and symbolic)
  67.         Device special and pipe
  68.     
  69.     UMSDOS is powerful enough to act as a ROOT file system for 
  70.     LINUX. From a Linux kernel standpoint, this is a true 
  71.     filesystem. Compile a kernel with UMSDOS, put it on a 
  72.     disquette, use rdev to specify the proper root partition 
  73.     (Any msdos partition with linux in it), and boot. In the 
  74.     following document, the --linux-.--- will be named EMD 
  75.     (Extension to Msdos Directory).
  76.     
  77.     3        General strategy                                            
  78.     
  79.     UMSDOS operates on top of the MSDOS fs for LINUX. Using the 
  80.     VFS function table, UMSDOS mostly intercept calls to MSDOS 
  81.     fs, do some translation and sometime carries itself the 
  82.     operation. Most of the job is directory search both in MSDOS 
  83.     fs and EMD.
  84.     
  85.     4        File name mangling                                          
  86.     
  87.     
  88.         [linux/fs/umsdos/mangle.c,261]
  89.         #Specification: file name / non MSDOS conforming / mangling
  90.     
  91.         Non MSDOS conforming file name must use some alias to fit
  92.         in the MSDOS name space.
  93.  
  94.  
  95.                                                              1
  96.  
  97.  
  98.         The strategy is simple. The name is simply truncated to
  99.         8 char. points are replace with underscore and a
  100.         number is given as an extension. This number correspond
  101.         to the entry number in the EMD file. The EMD file
  102.         only need to carry the real name.
  103.     
  104.         Upper case is also convert to lower case.
  105.         Control character are converted to #.
  106.         Space are converted to #.
  107.         The following character are also converted to #.
  108.             " * + , / : ; < = > ? [ \ ] | ~
  109.     
  110.         Sometime, the problem is not in MsDOS itself but in
  111.         command.com.
  112.     
  113.         [linux/fs/umsdos/mangle.c,26]
  114.         #Specification: file name / non MSDOS conforming / mangling
  115.     
  116.         Each non MSDOS conforming file has a special extension
  117.         build from the entry position in the EMD file.
  118.     
  119.         This number is then transform in a base 32 number, where
  120.         each digit is expressed like hexadecimal number, using
  121.         digit and letter, except it uses 22 letters from 'a' to 'v'.
  122.         The number 32 comes from 2**5. It is faster to split a binary
  123.         number using a base which is a power of two. And I was 32
  124.         when I started this project. Pick your answer :-) .
  125.     
  126.         If the result is '0', it is replace with '_', simply
  127.         to make it odd.
  128.     
  129.         This is true for the first two character of the extension.
  130.         The last one is taken from a list of odd character, which
  131.         are:
  132.     
  133.             { } ( ) ! ` ^ & @
  134.     
  135.         With this scheme, we can produce 9216 ( 9* 32 * 32)
  136.         different extensions which should not clash with any useful
  137.         extension already popular or meaningful. Since most directory
  138.         have much less than 32 * 32 files in it, the first character
  139.         of the extension of any mangle name will be {.
  140.     
  141.         Here are the reason to do this (this kind of mangling).
  142.     
  143.         -The mangling is deterministic. Just by the extension, we
  144.          are able to locate the entry in the EMD file.
  145.     
  146.         -By keeping to beginning of the file name almost unchanged,
  147.          we are helping the MSDOS user.
  148.     
  149.         -The mangling produces names not too ugly, so an msdos user
  150.          may live with it (remember it, type it, etc...).
  151.     
  152.         -The mangling produces names ugly enough so no one will
  153.          ever think of using such a name in real life. This is not
  154.          fool proof. I don't think there is a total solution to this.
  155.     
  156.  
  157.  
  158.                                                              2
  159.  
  160.  
  161.         [linux/fs/umsdos/mangle.c,306]
  162.         #Specification: file name / MSDOS devices / mangling
  163.     
  164.         To avoid unreachable file from MsDOS, any MsDOS conforming
  165.         file with a basename equal to one of the MsDOS pseudo
  166.         devices will be mangled.
  167.     
  168.         If a file such as "prn" was created, it would be unreachable
  169.         under MsDOS because prn is assumed to be the printer, even
  170.         if the file does have an extension.
  171.     
  172.         Since the extension is unimportant to MsDOS, we must patch
  173.         the basename also. We simply insert a minus '-'. To avoid
  174.         conflict with valid file with a minus in front (such as
  175.         "-prn"), we add an mangled extension like any other
  176.         mangled file name.
  177.     
  178.         Here is the list of DOS pseudo devices:
  179.     
  180.             "prn","con","aux","nul",
  181.             "lpt1","lpt2","lpt3","lpt4",
  182.             "com1","com2","com3","com4",
  183.             "clock$"
  184.     
  185.         and some standard ones for common DOS programs
  186.     
  187.             "emmxxxx0","xmsxxxx0","setverxx"
  188.     
  189.         (Thanks to Chris Hall <CAH17@PHOENIX.CAMBRIDGE.AC.UK>
  190.          for pointing these to me).
  191.     
  192.         Is there one missing ?
  193.     
  194.         [linux/fs/umsdos/mangle.c,257]
  195.         #Specification: file name / --linux-.---
  196.     
  197.         The name of the EMD file --linux-.--- is map to a mangled
  198.         name. So UMSDOS does not restrict its use.
  199.     
  200.         [linux/fs/umsdos/mangle.c,147]
  201.         #Specification: file name / non MSDOS conforming / base length 0
  202.     
  203.         file name beginning with a period '.' are invalid for MsDOS.
  204.         It needs absolutely a base name. So the file name is mangled
  205.     
  206.         [linux/fs/umsdos/mangle.c,220]
  207.         #Specification: file name / non MSDOS conforming / mangling clash
  208.     
  209.         To avoid clash with the umsdos mangling, any file
  210.         with a special character as the first character
  211.         of the extension will be mangled. This solve the
  212.         following problem:
  213.     
  214.         touch FILE
  215.         # FILE is invalid for DOS, so mangling is applied
  216.         # file.{_1 is created in the DOS directory
  217.         touch file.{_1
  218.         # To UMSDOS file point to a single DOS entry.
  219.  
  220.  
  221.                                                              3
  222.  
  223.  
  224.         # So file.{_1 has to be mangled.
  225.     
  226.         [linux/fs/umsdos/mangle.c,212]
  227.         #Specification: file name / non MSDOS conforming / last char == .
  228.     
  229.         If the last character of a file name is
  230.         a period, mangling is applied. MsDOS do
  231.         not support those file name.
  232.     
  233.         [linux/fs/umsdos/mangle.c,139]
  234.         #Specification: file name / too long
  235.     
  236.         If a file name exceed UMSDOS maxima, the file name is silently
  237.         truncated. This makes it conformant with the other file system
  238.         of Linux (minix and ext2 at least).
  239.     
  240.     
  241.     5        --linux-.---: the EMD file                                  
  242.     
  243.     The strategy for inode management. UMSDOS lets the MSDOS fs 
  244.     run and does simple transformation to the in core inode 
  245.     content. It also adds information at the end of the inode 
  246.     structure. See /usr/include/linux/umsdos_fs_i.h.
  247.     
  248.         [/usr/include/linux/umsdos_fs.h,47]
  249.         #Specification: EMD file / record size
  250.     
  251.         Entry are 64 bytes wide in the EMD file. It allows for a 30 characters
  252.         name. If a name is longer, contiguous entries are allocated. So a
  253.         umsdos_dirent may span multiple records.
  254.     
  255.         [linux/fs/umsdos/emd.c,282]
  256.         #Specification: EMD file structure
  257.     
  258.         The EMD file uses a fairly simple layout. It is made of records
  259.         (UMSDOS_REC_SIZE == 64). When a name can't be written is a single
  260.         record, multiple contiguous record are allocated.
  261.     
  262.         [linux/fs/umsdos/emd.c,183]
  263.         #Specification: EMD file / empty entries
  264.     
  265.         Unused entry in the EMD file are identify
  266.         by the name_len field equal to 0. However to
  267.         help future extension (or bug correction :-( ),
  268.         empty entries are filled with 0.
  269.     
  270.         [/usr/include/linux/umsdos_fs_i.h,80]
  271.         #Specification: strategy / in memory inode
  272.     
  273.         Here is the information specific to the inode of the UMSDOS file
  274.         system. This information is added to the end of the standard struct
  275.         inode. Each file system has its own extension to struct inode,
  276.         so do the umsdos file system.
  277.     
  278.         The strategy is to have the umsdos_inode_info as a superset of
  279.         the msdos_inode_info, since most of the time the job is done
  280.         by the msdos fs code.
  281.  
  282.  
  283.                                                              4
  284.  
  285.  
  286.         So we duplicate the msdos_inode_info, and add our own info at the
  287.         end.
  288.     
  289.         For all file type (and directory) the inode has a reference to:
  290.             the directory which hold this entry: i_dir_owner
  291.             The EMD file of i_dir_owner: i_emd_owner
  292.             The offset in this EMD file of the entry: pos
  293.     
  294.         For directory, we also have a reference to the inode of its
  295.         own EMD file. Also, we have dir_locking_info to help synchronise
  296.         file creation and file lookup. This data is sharing space with
  297.         the pipe_inode_info not used by directory. See also msdos_fs_i.h
  298.         for more information about pipe_inode_info and msdos_inode_info.
  299.     
  300.         Special file and fifo do have an inode which correspond to an
  301.         empty MSDOS file.
  302.     
  303.         symlink are processed mostly like regular file. The content is the
  304.         link.
  305.     
  306.         fifos add there own extension to the inode. I have reserved some
  307.         space for fifos side by side with msdos_inode_info. This is just
  308.         to for the show, because msdos_inode_info already include the
  309.         pipe_inode_info.
  310.     
  311.         The UMSDOS specific extension is placed after the union.
  312.     
  313.         [/usr/include/linux/umsdos_fs_i.h,10]
  314.         #Specification: strategy / in memory inode
  315.     
  316.         Here is the information specific to the inode of the UMSDOS file
  317.         system. This information is added to the end of the standard struct
  318.         inode. Each file system has its own extension to struct inode,
  319.         so do the umsdos file system.
  320.     
  321.         The strategy is to have the umsdos_inode_info as a superset of
  322.         the msdos_inode_info, since most of the time the job is done
  323.         by the msdos fs code.
  324.     
  325.         So we duplicate the msdos_inode_info, and add our own info at the
  326.         end.
  327.     
  328.         For all file type (and directory) the inode has a reference to:
  329.             the directory which hold this entry: i_dir_owner
  330.             The EMD file of i_dir_owner: i_emd_owner
  331.             The offset in this EMD file of the entry: pos
  332.     
  333.         For directory, we also have a reference to the inode of its
  334.         own EMD file. Also, we have dir_locking_info to help synchronise
  335.         file creation and file lookup. This data is sharing space with
  336.         the pipe_inode_info not used by directory. See also msdos_fs_i.h
  337.         for more information about pipe_inode_info and msdos_inode_info.
  338.     
  339.         Special file and fifo do have an inode which correspond to an
  340.         empty MSDOS file.
  341.     
  342.         symlink are processed mostly like regular file. The content is the
  343.         link.
  344.  
  345.  
  346.                                                              5
  347.  
  348.  
  349.         fifos add there own extension to the inode. I have reserved some
  350.         space for fifos side by side with msdos_inode_info. This is just
  351.         to for the show, because msdos_inode_info already include the
  352.         pipe_inode_info.
  353.     
  354.         The UMSDOS specific extension is placed after the union.
  355.     
  356.         [linux/fs/umsdos/emd.c,194]
  357.         #Specification: EMD file / spare bytes
  358.     
  359.         10 bytes are unused in each record of the EMD. They
  360.         are set to 0 all the time. So it will be possible
  361.         to do new stuff and rely on the state of those
  362.         bytes in old EMD file around.
  363.     
  364.     
  365.     6        Hard links                                                  
  366.     
  367.     
  368.         [linux/fs/umsdos/namei.c,469]
  369.         #Specification: hard link / strategy
  370.     
  371.         Well ... hard link are difficult to implement on top of an
  372.         MsDOS fat file system. Unlike UNIX file systems, there are no
  373.         inode. A directory entry hold the functionality of the inode
  374.         and the entry.
  375.     
  376.         We will used the same strategy as a normal Unix file system
  377.         (with inode) except we will do it symbolically (using paths).
  378.     
  379.         Because anything can happen during a DOS session (defragment,
  380.         directory sorting, etc...), we can't rely on MsDOS pseudo
  381.         inode number to record the link. For this reason, the link
  382.         will be done using hidden symbolic links. The following
  383.         scenario illustrate how it work.
  384.     
  385.         Given a file /foo/file
  386.     
  387.             ln /foo/file /tmp/file2
  388.     
  389.             become internally
  390.     
  391.             mv /foo/file /foo/-LINK1
  392.             ln -s /foo/-LINK1 /foo/file
  393.             ln -s /foo/-LINK1 /tmp/file2
  394.     
  395.         Using this strategy, we can operate on /foo/file or /foo/file2.
  396.         We can remove one and keep the other, like a normal Unix hard link.
  397.         We can rename /foo/file or /tmp/file2 independently.
  398.     
  399.         The entry -LINK1 will be hidden. It will hold a link count.
  400.         When all link are erased, the hidden file is erased too.
  401.     
  402.         [linux/fs/umsdos/namei.c,541]
  403.         #Specification: hard link / directory
  404.     
  405.         A hard link can't be made on a directory. EPERM is returned
  406.  
  407.  
  408.                                                              6
  409.  
  410.  
  411.         in this case.
  412.     
  413.         [linux/fs/umsdos/emd.c,405]
  414.         #Specification: hard link / hidden name
  415.     
  416.         When a hard link is created, the original file is renamed
  417.         to a hidden name. The name is "..LINKNNN" where NNN is a
  418.         number define from the entry offset in the EMD file.
  419.     
  420.         [linux/fs/umsdos/namei.c,560]
  421.         #Specification: hard link / first hard link
  422.     
  423.         The first time a hard link is done on a file, this
  424.         file must be renamed and hidden. Then an internal
  425.         symbolic link must be done on the hidden file.
  426.     
  427.         The second link is done after on this hidden file.
  428.     
  429.         It is expected that the Linux MSDOS file system
  430.         keeps the same pseudo inode when a rename operation
  431.         is done on a file in the same directory.
  432.     
  433.         [linux/fs/umsdos/namei.c,912]
  434.         #Specification: hard link / deleting a link
  435.     
  436.         When we deletes a file, and this file is a link
  437.         we must subtract 1 to the nlink field of the
  438.         hidden link.
  439.     
  440.         If the count goes to 0, we delete this hidden
  441.         link too.
  442.     
  443.     
  444.     7        Symbolic links                                              
  445.     
  446.     
  447.         [linux/fs/umsdos/namei.c,407]
  448.         #Specification: symbolic links / strategy
  449.     
  450.         A symbolic link is simply a file which hold a path. It is
  451.         implemented as a normal MSDOS file (not very space efficient :-()
  452.     
  453.         I see 2 different way to do it. One is to place the link data
  454.         in unused entry of the EMD file. The other is to have a separate
  455.         file dedicated to hold all symbolic links data.
  456.     
  457.         Lets go for simplicity...
  458.     
  459.     
  460.     8        Special file                                                
  461.     
  462.     
  463.         [linux/fs/umsdos/namei.c,729]
  464.         #Specification: Special files / strategy
  465.     
  466.         Device special file, pipes, etc ... are created like normal
  467.  
  468.  
  469.                                                              7
  470.  
  471.  
  472.         file in the msdos file system. Of course they remain empty.
  473.     
  474.         One strategy was to create those files only in the EMD file
  475.         since they were not important for MSDOS. The problem with
  476.         that, is that there were not getting inode number allocated.
  477.         The MSDOS filesystems is playing a nice game to fake inode
  478.         number, so why not use it.
  479.     
  480.         The absence of inode number compatible with those allocated
  481.         for ordinary files was causing major trouble with hard link
  482.         in particular and other parts of the kernel I guess.
  483.     
  484.     
  485.     9        Pseudo root                                                 
  486.     
  487.     
  488.         [linux/fs/umsdos/inode.c,416]
  489.         #Specification: pseudo root / mount
  490.     
  491.         When a umsdos fs is mounted, a special handling is done
  492.         if it is the root partition. We check for the presence
  493.         of the file /linux/etc/init or /linux/etc/rc.
  494.         If one is there, we do a chroot("/linux").
  495.     
  496.         We check both because (see init/main.c) the kernel
  497.         try to exec init at different place and if it fails
  498.         it tries /bin/sh /etc/rc. To be consistent with
  499.         init/main.c, many more test would have to be done
  500.         to locate init. Any complain ?
  501.     
  502.         The chroot is done manually in init/main.c but the
  503.         info (the inode) is located at mount time and store
  504.         in a global variable (pseudo_root) which is used at
  505.         different place in the umsdos driver. There is no
  506.         need to store this variable elsewhere because it
  507.         will always be one, not one per mount.
  508.     
  509.         This feature allows the installation
  510.         of a linux system within a DOS system in a subdirectory.
  511.     
  512.         A user may install its linux stuff in c:\linux
  513.         avoiding any clash with existing DOS file and subdirectory.
  514.         When linux boots, it hides this fact, showing a normal
  515.         root directory with /etc /bin /tmp ...
  516.     
  517.         The word "linux" is hardcoded in /usr/include/linux/umsdos_fs.h
  518.         in the macro UMSDOS_PSDROOT_NAME.
  519.     
  520.         [linux/fs/umsdos/dir.c,69]
  521.         #Specification: pseudo root / directory /DOS
  522.     
  523.         When umsdos operates in pseudo root mode (C:\linux is the
  524.         linux root), it simulate a directory /DOS which points to
  525.         the real root of the file system.
  526.     
  527.         [linux/fs/umsdos/dir.c,486]
  528.         #Specification: pseudo root / DOS hard coded
  529.  
  530.  
  531.                                                              8
  532.  
  533.  
  534.         The pseudo sub-directory DOS in the pseudo root is hard coded.
  535.         The name is DOS. This is done this way to help standardised
  536.         the umsdos layout. The idea is that from now on /DOS is
  537.         a reserved path and nobody will think of using such a path
  538.         for a package.
  539.     
  540.         [linux/fs/umsdos/dir.c,517]
  541.         #Specification: pseudo root / .. in real root
  542.     
  543.         Whenever a lookup is those in the real root for
  544.         the directory .., and pseudo root is active, the
  545.         pseudo root is returned.
  546.     
  547.         [linux/fs/umsdos/namei.c,166]
  548.         #Specification: pseudo root / any file creation /DOS
  549.     
  550.         The pseudo sub-directory /DOS can't be created!
  551.         EEXIST is returned.
  552.     
  553.         The pseudo sub-directory /DOS can't be removed!
  554.         EPERM is returned.
  555.     
  556.         [linux/fs/umsdos/dir.c,586]
  557.         #Specification: pseudo root / dir lookup
  558.     
  559.         For the same reason as readdir, a lookup in /DOS for
  560.         the pseudo root directory (linux) will fail.
  561.     
  562.         [linux/fs/umsdos/rdir.c,81]
  563.         #Specification: pseudo root / DOS/..
  564.     
  565.         In the real root directory (c:\), the directory ..
  566.         is the pseudo root (c:\linux).
  567.     
  568.         [linux/fs/umsdos/rdir.c,90]
  569.         #Specification: pseudo root / DOS/linux
  570.     
  571.         Even in the real root directory (c:\), the directory
  572.         /linux won't show
  573.     
  574.         [linux/fs/umsdos/dir.c,548]
  575.         #Specification: pseudo root / lookup(DOS)
  576.     
  577.         A lookup of DOS in the pseudo root will always succeed
  578.         and return the inode of the real root.
  579.     
  580.         [linux/fs/umsdos/dir.c,169]
  581.         #Specification: pseudo root / reading real root
  582.     
  583.         The pseudo root (/linux) is logically
  584.         erased from the real root. This mean that
  585.         ls /DOS, won't show "linux". This avoids
  586.         infinite recursion /DOS/linux/DOS/linux while
  587.         walking the file system.
  588.     
  589.         [linux/fs/umsdos/rdir.c,129]
  590.         #Specification: pseudo root / rmdir /DOS
  591.     
  592.  
  593.  
  594.                                                              9
  595.  
  596.  
  597.         The pseudo sub-directory /DOS can't be removed!
  598.         This is done even if the pseudo root is not a Umsdos
  599.         directory anymore (very unlikely), but an accident (under
  600.         MsDOS) is always possible.
  601.     
  602.         EPERM is returned.
  603.     
  604.     
  605.     10       Dual mode                                                   
  606.     
  607.     
  608.         [linux/fs/umsdos/rdir.c,179]
  609.         #Specification: dual mode / introduction
  610.     
  611.         One goal of UMSDOS is to allow a practical and simple coexistence
  612.         between MsDOS and Linux in a single partition. Using the EMD file
  613.         in each directory, UMSDOS add Unix semantics and capabilities to
  614.         normal DOS file system. To help and simplify coexistence, here is
  615.         the logic related to the EMD file.
  616.     
  617.         If it is missing, then the directory is managed by the MsDOS driver.
  618.         The names are limited to DOS limits (8.3). No links, no device special
  619.         and pipe and so on.
  620.     
  621.         If it is there, it is the directory. If it is there but empty, then
  622.         the directory looks empty. The utility umssync allows synchronisation
  623.         of the real DOS directory and the EMD.
  624.     
  625.         Whenever umssync is applied to a directory without EMD, one is
  626.         created on the fly. The directory is promoted to full unix semantic.
  627.         Of course, the ls command will show exactly the same content as before
  628.         the umssync session.
  629.     
  630.         It is believed that the user/admin will promote directories to unix
  631.         semantic as needed.
  632.     
  633.         The strategy to implement this is to use two function table (struct
  634.         inode_operations). One for true UMSDOS directory and one for directory
  635.         with missing EMD.
  636.     
  637.         Functions related to the DOS semantic (but aware of UMSDOS) generally
  638.         have a "r" prefix (r for real) such as UMSDOS_rlookup, to differentiate
  639.         from the one with full UMSDOS semantic.
  640.     
  641.         [linux/fs/umsdos/rdir.c,113]
  642.         #Specification: dual mode / rmdir in a DOS directory
  643.     
  644.         In a DOS (not EMD in it) directory, we use a reverse strategy
  645.         compared with an Umsdos directory. We assume that a subdirectory
  646.         of a DOS directory is also a DOS directory. This is not always
  647.         true (umssync may be used anywhere), but make sense.
  648.     
  649.         So we call msdos_rmdir() directly. If it failed with a -ENOTEMPTY
  650.         then we check if it is a Umsdos directory. We check if it is
  651.         really empty (only . .. and --linux-.--- in it). If it is true
  652.         we remove the EMD and do a msdos_rmdir() again.
  653.     
  654.  
  655.  
  656.                                                             10
  657.  
  658.  
  659.         In a Umsdos directory, we assume all subdirectory are also
  660.         Umsdos directory, so we check the EMD file first.
  661.     
  662.         [linux/fs/umsdos/namei.c,690]
  663.         #Specification: mkdir / umsdos directory / create EMD
  664.     
  665.         When we created a new sub-directory in a UMSDOS
  666.         directory (one with full UMSDOS semantic), we
  667.         create immediately an EMD file in the new
  668.         sub-directory so it inherit UMSDOS semantic.
  669.     
  670.     
  671.     11       Miscellaneous                                               
  672.     
  673.     
  674.     11.1     UMSDOS_create                                               
  675.     
  676.     
  677.         [linux/fs/umsdos/namei.c,55]
  678.         #Specification: file creation / not atomic
  679.     
  680.         File creation is a two step process. First we create (allocate)
  681.         an entry in the EMD file and then (using the entry offset) we
  682.         build a unique name for MSDOS. We create this name in the msdos
  683.         space.
  684.     
  685.         We have to use semaphore (sleep_on/wake_up) to prevent lookup
  686.         into a directory when we create a file or directory and to
  687.         prevent creation while a lookup is going on. Since many lookup
  688.         may happen at the same time, the semaphore is a counter.
  689.     
  690.         Only one creation is allowed at the same time. This protection
  691.         may not be necessary. The problem arise mainly when a lookup
  692.         or a readdir is done while a file is partially created. The
  693.         lookup process see that as a "normal" problem and silently
  694.         erase the file from the EMD file. Normal because a file
  695.         may be erased during a MSDOS session, but not removed from
  696.         the EMD file.
  697.     
  698.         The locking is done on a directory per directory basis. Each
  699.         directory inode has its wait_queue.
  700.     
  701.         For some operation like hard link, things even get worse. Many
  702.         creation must occur at once (atomic). To simplify the design
  703.         a process is allowed to recursively lock the directory for
  704.         creation. The pid of the locking process is kept along with
  705.         a counter so a second level of locking is granted or not.
  706.     
  707.         [linux/fs/umsdos/namei.c,177]
  708.         #Specification: create / . and ..
  709.     
  710.         If one try to creates . or .., it always fail and return
  711.         EEXIST.
  712.     
  713.         If one try to delete . or .., it always fail and return
  714.         EPERM.
  715.  
  716.  
  717.                                                             11
  718.  
  719.  
  720.         This should be test at the VFS layer level to avoid
  721.         duplicating this in all file systems. Any comments ?
  722.     
  723.     
  724.     11.2     UMSDOS_ioctl_dir                                            
  725.     
  726.     
  727.         [linux/fs/umsdos/ioctl.c,29]
  728.         #Specification: ioctl / acces
  729.     
  730.         Only root (effective id) is allowed to do IOCTL on directory
  731.         in UMSDOS. EPERM is returned for other user.
  732.     
  733.         [linux/fs/umsdos/ioctl.c,37]
  734.         #Specification: ioctl / prototypes
  735.     
  736.         The official prototype for the umsdos ioctl on directory
  737.         is:
  738.     
  739.         int ioctl (
  740.             int fd,     // File handle of the directory
  741.             int cmd,    // command
  742.             struct umsdos_ioctl *data)
  743.     
  744.         The struct and the commands are defined in linux/umsdos_fs.h.
  745.     
  746.         umsdos_progs/umsdosio.c provide an interface in C++ to all
  747.         these ioctl. umsdos_progs/udosctl is a small utility showing
  748.         all this.
  749.     
  750.         These ioctl generally allow one to work on the EMD or the
  751.         DOS directory independently. These are essential to implement
  752.         the synchronise.
  753.     
  754.         [linux/fs/umsdos/ioctl.c,58]
  755.         #Specification: ioctl / UMSDOS_GETVERSION
  756.     
  757.         The field version and release of the structure
  758.         umsdos_ioctl are filled with the version and release
  759.         number of the fs code in the kernel. This will allow
  760.         some form of checking. Users won't be able to run
  761.         incompatible utility such as the synchroniser (umssync).
  762.         umsdos_progs/umsdosio.c enforce this checking.
  763.     
  764.         Return always 0.
  765.     
  766.         [linux/fs/umsdos/ioctl.c,72]
  767.         #Specification: ioctl / UMSDOS_READDIR_DOS
  768.     
  769.         One entry is read from the DOS directory at the current
  770.         file position. The entry is put as is in the dos_dirent
  771.         field of struct umsdos_ioctl.
  772.     
  773.         Return > 0 if success.
  774.     
  775.         [linux/fs/umsdos/ioctl.c,193]
  776.         #Specification: ioctl / UMSDOS_RMDIR_DOS
  777.  
  778.  
  779.                                                             12
  780.  
  781.  
  782.         The dos_dirent field of the struct umsdos_ioctl is used to
  783.         execute a msdos_unlink operation. The d_name and d_reclen
  784.         fields are used.
  785.     
  786.         Return 0 if success.
  787.     
  788.         [linux/fs/umsdos/ioctl.c,204]
  789.         #Specification: ioctl / UMSDOS_STAT_DOS
  790.     
  791.         The dos_dirent field of the struct umsdos_ioctl is
  792.         used to execute a stat operation in the DOS directory.
  793.         The d_name and d_reclen fields are used.
  794.     
  795.         The following field of umsdos_ioctl.stat are filled.
  796.     
  797.         st_ino,st_mode,st_size,st_atime,st_mtime,st_ctime,
  798.         Return 0 if success.
  799.     
  800.         [linux/fs/umsdos/ioctl.c,182]
  801.         #Specification: ioctl / UMSDOS_UNLINK_DOS
  802.     
  803.         The dos_dirent field of the struct umsdos_ioctl is used to
  804.         execute a msdos_unlink operation. The d_name and d_reclen
  805.         fields are used.
  806.     
  807.         Return 0 if success.
  808.     
  809.         [linux/fs/umsdos/ioctl.c,147]
  810.         #Specification: ioctl / UMSDOS_CREAT_EMD
  811.     
  812.         The umsdos_dirent field of the struct umsdos_ioctl is used
  813.         as is to create a new entry in the EMD of the directory.
  814.         The DOS directory is not modified.
  815.         No validation is done (yet).
  816.     
  817.         Return 0 if success.
  818.     
  819.         [linux/fs/umsdos/ioctl.c,81]
  820.         #Specification: ioctl / UMSDOS_READDIR_EMD
  821.     
  822.         One entry is read from the EMD at the current
  823.         file position. The entry is put as is in the umsdos_dirent
  824.         field of struct umsdos_ioctl. The corresponding mangled
  825.         DOS entry name is put in the dos_dirent field.
  826.     
  827.         All entries are read including hidden links. Blank
  828.         entries are skipped.
  829.     
  830.         Return > 0 if success.
  831.     
  832.         [linux/fs/umsdos/ioctl.c,164]
  833.         #Specification: ioctl / UMSDOS_UNLINK_EMD
  834.     
  835.         The umsdos_dirent field of the struct umsdos_ioctl is used
  836.         as is to remove an entry from the EMD of the directory.
  837.         No validation is done (yet). The mode field is used
  838.         to validate S_ISDIR or S_ISREG.
  839.     
  840.  
  841.  
  842.                                                             13
  843.  
  844.  
  845.         Return 0 if success.
  846.     
  847.         [linux/fs/umsdos/ioctl.c,228]
  848.         #Specification: ioctl / UMSDOS_DOS_SETUP
  849.     
  850.         The UMSDOS_DOS_SETUP ioctl allow changing the
  851.         default permission of the MsDOS file system driver
  852.         on the fly. The MsDOS driver apply global permission
  853.         to every file and directory. Normally these permissions
  854.         are controlled by a mount option. This is not
  855.         available for root partition, so a special utility
  856.         (umssetup) is provided to do this, normally in
  857.         /etc/rc.local.
  858.     
  859.         Be aware that this apply ONLY to MsDOS directory
  860.         (those without EMD --linux-.---). Umsdos directory
  861.         have independent (standard) permission for each
  862.         and every file.
  863.     
  864.         The field umsdos_dirent provide the information needed.
  865.         umsdos_dirent.uid and gid sets the owner and group.
  866.         umsdos_dirent.mode set the permissions flags.
  867.     
  868.         [linux/fs/umsdos/ioctl.c,124]
  869.         #Specification: ioctl / UMSDOS_INIT_EMD
  870.     
  871.         The UMSDOS_INIT_EMD command make sure the EMD
  872.         exist for a directory. If it does not, it is
  873.         created. Also, it makes sure the directory functions
  874.         table (struct inode_operations) is set to the UMSDOS
  875.         semantic. This mean that umssync may be applied to
  876.         an "opened" msdos directory, and it will change behavior
  877.         on the fly.
  878.     
  879.         Return 0 if success.
  880.     
  881.     
  882.     11.3     UMSDOS_lookup                                               
  883.     
  884.     
  885.         [linux/fs/umsdos/dir.c,526]
  886.         #Specification: locating .. / strategy
  887.     
  888.         We use the msdos filesystem to locate the parent directory.
  889.         But it is more complicated than that.
  890.     
  891.         We have to step back even further to
  892.         get the parent of the parent, so we can get the EMD
  893.         of the parent of the parent. Using the EMD file, we can
  894.         locate all the info on the parent, such a permissions
  895.         and owner.
  896.     
  897.         [linux/fs/umsdos/dir.c,562]
  898.         #Specification: umsdos / lookup
  899.     
  900.         A lookup for a file is done in two step. First, we locate
  901.         the file in the EMD file. If not present, we return
  902.  
  903.  
  904.                                                             14
  905.  
  906.  
  907.         an error code (-ENOENT). If it is there, we repeat the
  908.         operation on the msdos file system. If this fails, it means
  909.         that the file system is not in sync with the emd file.
  910.         We silently remove this entry from the emd file,
  911.         and return ENOENT.
  912.     
  913.         [linux/fs/umsdos/dir.c,284]
  914.         #Specification: umsdos / lookup / inode info
  915.     
  916.         After successfully reading an inode from the MSDOS
  917.         filesystem, we use the EMD file to complete it.
  918.         We update the following field.
  919.     
  920.         uid, gid, atime, ctime, mtime, mode.
  921.     
  922.         We rely on MSDOS for mtime. If the file
  923.         was modified during an MSDOS session, at least
  924.         mtime will be meaningful. We do this only for regular
  925.         file.
  926.     
  927.         We don't rely on MSDOS for mtime for directory because
  928.         the MSDOS directory date is creation time (strange
  929.         MSDOS behavior) which fit nowhere in the three UNIX
  930.         time stamp.
  931.     
  932.         [linux/fs/umsdos/dir.c,309]
  933.         #Specification: umsdos / i_nlink
  934.     
  935.         The nlink field of an inode is maintain by the MSDOS file system
  936.         for directory and by UMSDOS for other file. The logic is that
  937.         MSDOS is already figuring out what to do for directories and
  938.         does nothing for other files. For MSDOS, there are no hard link
  939.         so all file carry nlink==1. UMSDOS use some info in the
  940.         EMD file to plug the correct value.
  941.     
  942.     
  943.     11.4     UMSDOS_notify_change                                        
  944.     
  945.     
  946.         [linux/fs/umsdos/inode.c,351]
  947.         #Specification: notify_change / msdos fs
  948.     
  949.         notify_change operation are done only on the
  950.         EMD file. The msdos fs is not even called.
  951.     
  952.         [linux/fs/umsdos/inode.c,295]
  953.         #Specification: root inode / attributes
  954.     
  955.         I don't know yet how this should work. Normally
  956.         the attributes (permissions bits, owner, times) of
  957.         a directory are stored in the EMD file of its parent.
  958.     
  959.         One thing we could do is store the attributes of the root
  960.         inode in its own EMD file. A simple entry named "." could
  961.         be used for this special case. It would be read once
  962.         when the file system is mounted and update in
  963.         UMSDOS_notify_change() (right here).
  964.  
  965.  
  966.                                                             15
  967.  
  968.  
  969.         I am not sure of the behavior of the root inode for
  970.         a real UNIX file system. For now, this is a nop.
  971.     
  972.         [linux/fs/umsdos/inode.c,288]
  973.         #Specification: notify_change / i_nlink > 0
  974.     
  975.         notify change is only done for inode with nlink > 0. An inode
  976.         with nlink == 0 is no longer associated with any entry in
  977.         the EMD file, so there is nothing to update.
  978.     
  979.     
  980.     11.5     UMSDOS_readdir                                              
  981.     
  982.     
  983.         [linux/fs/umsdos/dir.c,132]
  984.         #Specification: umsdos / readdir
  985.     
  986.         umsdos_readdir() should fill a struct dirent with
  987.         an inode number. The cheap way to get it is to
  988.         do a lookup in the MSDOS directory for each
  989.         entry processed by the readdir() function.
  990.         This is not very efficient, but very simple. The
  991.         other way around is to maintain a copy of the inode
  992.         number in the EMD file. This is a problem because
  993.         this has to be maintained in sync using tricks.
  994.         Remember that MSDOS (the OS) does not update the
  995.         modification time (mtime) of a directory. There is
  996.         no easy way to tell that a directory was modified
  997.         during a DOS session and synchronise the EMD file.
  998.     
  999.         Suggestion welcome.
  1000.     
  1001.         So the easy way is used!
  1002.     
  1003.         [linux/fs/umsdos/dir.c,83]
  1004.         #Specification: readdir / . and ..
  1005.     
  1006.         The msdos filesystem manage the . and .. entry properly
  1007.         so the EMD file won't hold any info about it.
  1008.     
  1009.         In readdir, we assume that for the root directory
  1010.         the read position will be 0 for ".", 1 for "..". For
  1011.         a non root directory, the read position will be 0 for "."
  1012.         and 32 for "..".
  1013.     
  1014.         [linux/fs/umsdos/dir.c,204]
  1015.         #Specification: umsdos / readdir / not in MSDOS
  1016.     
  1017.         During a readdir operation, if the file is not
  1018.         in the MSDOS directory anymore, the entry is
  1019.         removed from the EMD file silently.
  1020.     
  1021.     
  1022.     11.6     mount and UMSDOS_remount_fs                                 
  1023.     
  1024.     
  1025.  
  1026.  
  1027.                                                             16
  1028.  
  1029.  
  1030.         [linux/fs/umsdos/inode.c,394]
  1031.         #Specification: mount / options
  1032.     
  1033.         Umsdos run on top of msdos. Currently, it supports no
  1034.         mount option, but happily pass all option received to
  1035.         the msdos driver. I am not sure if all msdos mount option
  1036.         make sense with Umsdos. Here are at least those who
  1037.         are useful.
  1038.             uid=
  1039.             gid=
  1040.     
  1041.         These options affect the operation of umsdos in directories
  1042.         which do not have an EMD file. They behave like normal
  1043.         msdos directory, with all limitation of msdos.
  1044.     
  1045.     
  1046.     11.7     UMSDOS_rename                                               
  1047.     
  1048.     
  1049.         [linux/fs/umsdos/namei.c,1000]
  1050.         #Specification: rename / new name exist
  1051.     
  1052.         If the destination name already exist, it will
  1053.         silently be removed. EXT2 does it this way
  1054.         and this is the spec of SUNOS. So does UMSDOS.
  1055.     
  1056.         If the destination is an empty directory it will
  1057.         also be removed.
  1058.     
  1059.         [linux/fs/umsdos/namei.c,1008]
  1060.         #Specification: rename / new name exist / possible flaw
  1061.     
  1062.         The code to handle the deletion of the target (file
  1063.         and directory) use to be in umsdos_rename_f, surrounded
  1064.         by proper directory locking. This was insuring that only
  1065.         one process could achieve a rename (modification) operation
  1066.         in the source and destination directory. This was also
  1067.         insuring the operation was "atomic".
  1068.     
  1069.         This has been changed because this was creating a kernel
  1070.         stack overflow (stack is only 4k in the kernel). To avoid
  1071.         the code doing the deletion of the target (if exist) has
  1072.         been moved to a upper layer. umsdos_rename_f is tried
  1073.         once and if it fails with EEXIST, the target is removed
  1074.         and umsdos_rename_f is done again.
  1075.     
  1076.         This makes the code cleaner and (not sure) solve a
  1077.         deadlock problem one tester was experiencing.
  1078.     
  1079.         The point is to mention that possibly, the semantic of
  1080.         "rename" may be wrong. Anyone dare to check that :-)
  1081.         Be aware that IF it is wrong, to produce the problem you
  1082.         will need two process trying to rename a file to the
  1083.         same target at the same time. Again, I am not sure it
  1084.         is a problem at all.
  1085.     
  1086.     
  1087.  
  1088.  
  1089.                                                             17
  1090.  
  1091.  
  1092.     11.8     Data structure                                              
  1093.     
  1094.     
  1095.         [linux/fs/umsdos/inode.c,177]
  1096.         #Specification: inode / umsdos info
  1097.     
  1098.         The first time an inode is seen (inode->i_count == 1),
  1099.         the inode number of the EMD file which control this inode
  1100.         is tagged to this inode. It allows operation such
  1101.         as notify_change to be handled.
  1102.     
  1103.     
  1104.     11.9     Inode management                                            
  1105.     
  1106.     
  1107.         [linux/fs/umsdos/inode.c,242]
  1108.         #Specification: Inode / post initialisation
  1109.     
  1110.         To completely initialise an inode, we need access to the owner
  1111.         directory, so we can locate more info in the EMD file. This is
  1112.         not available the first time the inode is access, we use
  1113.         a value in the inode to tell if it has been finally initialised.
  1114.     
  1115.         At first, we have tried testing i_count but it was causing
  1116.         problem. It is possible that two or more process use the
  1117.         newly accessed inode. While the first one block during
  1118.         the initialisation (probably while reading the EMD file), the
  1119.         others believe all is well because i_count > 1. They go banana
  1120.         with a broken inode. See umsdos_lookup_patch and umsdos_patch_inode.
  1121.     
  1122.     
  1123.     12       Synchronisation problems                                    
  1124.     
  1125.     
  1126.         [linux/fs/umsdos/namei.c,238]
  1127.         #Specification: create / file exist in DOS
  1128.     
  1129.         Here is a situation. Trying to create a file with
  1130.         UMSDOS. The file is unknown to UMSDOS but already
  1131.         exist in the DOS directory.
  1132.     
  1133.         Here is what we are NOT doing:
  1134.     
  1135.         We could silently assume that everything is fine
  1136.         and allows the creation to succeed.
  1137.     
  1138.         It is possible not all files in the partition
  1139.         are mean to be visible from linux. By trying to create
  1140.         those file in some directory, one user may get access
  1141.         to those file without proper permissions. Looks like
  1142.         a security hole to me. Off course sharing a file system
  1143.         with DOS is some kind of security hole :-)
  1144.     
  1145.         So ?
  1146.     
  1147.  
  1148.  
  1149.                                                             18
  1150.  
  1151.  
  1152.         We return EEXIST in this case.
  1153.         The same is true for directory creation.
  1154.     
  1155.         [linux/fs/umsdos/namei.c,685]
  1156.         #Specification: mkdir / Directory already exist in DOS
  1157.     
  1158.         We do the same thing as for file creation.
  1159.         For all user it is an error.
  1160.     
  1161.     
  1162.     13       Convention and style                                        
  1163.     
  1164.     
  1165.         [linux/fs/umsdos/inode.c,366]
  1166.         #Specification: function name / convention
  1167.     
  1168.         A simple convention for function name has been used in
  1169.         the UMSDOS file system. First all function use the prefix
  1170.         umsdos_ to avoid name clash with other part of the kernel.
  1171.     
  1172.         And standard VFS entry point use the prefix UMSDOS (upper case)
  1173.         so it's easier to tell them apart.
  1174.     
  1175.         [linux/fs/umsdos/namei.c,757]
  1176.         #Specification: style / iput strategy
  1177.     
  1178.         In the UMSDOS project, I am trying to apply a single
  1179.         programming style regarding inode management. Many
  1180.         entry point are receiving an inode to act on, and must
  1181.         do an iput() as soon as they are finished with
  1182.         the inode.
  1183.     
  1184.         For simple case, there is no problem. When you introduce
  1185.         error checking, you end up with many iput placed around the
  1186.         code.
  1187.     
  1188.         The coding style I use all around is one where I am trying
  1189.         to provide independent flow logic (I don't know how to
  1190.         name this). With this style, code is easier to understand
  1191.         but you rapidly get iput() all around. Here is an exemple
  1192.         of what I am trying to avoid.
  1193.     
  1194.         if (a){
  1195.             ...
  1196.             if(b){
  1197.                 ...
  1198.             }
  1199.             ...
  1200.             if (c){
  1201.                 // Complex state. Was b true ?
  1202.                 ...
  1203.             }
  1204.             ...
  1205.         }
  1206.         // Weird state
  1207.         if (d){
  1208.             // ...
  1209.  
  1210.  
  1211.                                                             19
  1212.  
  1213.  
  1214.         }
  1215.         // Was iput finally done ?
  1216.         return status;
  1217.     
  1218.         Here is the style I am using. Still sometime I do the
  1219.         first when things are very simple (or very complicated :-( )
  1220.     
  1221.         if (a){
  1222.             if (b){
  1223.                 ...
  1224.             }else if (c){
  1225.                 // A single state gets here
  1226.             }
  1227.         }else if (d){
  1228.             ...
  1229.         }
  1230.         return status;
  1231.     
  1232.         Again, while this help clarifying the code, I often get a lot
  1233.         of iput(), unlike the first style, where I can place few
  1234.         "strategic" iput(). "strategic" also mean, more difficult
  1235.         to place.
  1236.     
  1237.         So here is the style I will be using from now on in this project.
  1238.         There is always an iput() at the end of a function (which has
  1239.         to do an iput()). One iput by inode. There is also one iput()
  1240.         at the places where a successful operation is achieved. This
  1241.         iput() is often done by a sub-function (often from the msdos
  1242.         file system). So I get one too many iput() ? At the place
  1243.         where an iput() is done, the inode is simply nulled, disabling
  1244.         the last one.
  1245.     
  1246.         if (a){
  1247.             if (b){
  1248.                 ...
  1249.             }else if (c){
  1250.                 msdos_rmdir(dir,...);
  1251.                 dir = NULL;
  1252.             }
  1253.         }else if (d){
  1254.             ...
  1255.         }
  1256.         iput (dir);
  1257.         return status;
  1258.     
  1259.         Note that the umsdos_lockcreate() and umsdos_unlockcreate() function
  1260.         pair goes against this practice of "forgetting" the inode as soon
  1261.         as possible.
  1262.     
  1263.         [linux/fs/umsdos/inode.c,28]
  1264.         #Specification: convention / PRINTK Printk and printk
  1265.     
  1266.         Here is the convention for the use of printk inside fs/umsdos
  1267.     
  1268.         printk carry important message (error or status).
  1269.         Printk is for debugging (it is a macro defined at the beginning of
  1270.                most source.
  1271.         PRINTK is a nulled Printk macro.
  1272.  
  1273.  
  1274.                                                             20
  1275.  
  1276.  
  1277.         This convention makes the source easier to read, and Printk easier
  1278.         to shut off.
  1279.     
  1280.     
  1281.     14       Weakness and features                                       
  1282.     
  1283.     The UMSDOS file system is somewhat a compromise. Here are 
  1284.     the drawback. -Space efficiency. The minimal allocation unit 
  1285.     is generally 2k. Also, the MsDOS FAT fs do not support 
  1286.     sparse file (file with gap of unallocated blocks). -General 
  1287.     performance. UMSDOS run piggy back on top of another FS. 
  1288.     This means two directory structure to maintain. -Maximum 
  1289.     number of files is limited to 64k. It should be a good fs 
  1290.     for many purpose, especially if you have to coexist with 
  1291.     DOS. UMSDOS is trying to emulate the UNIX semantics for file 
  1292.     system. Here are the known differences and weakness.
  1293.     
  1294.         [linux/fs/umsdos/namei.c,503]
  1295.         #Specification: weakness / hard link
  1296.     
  1297.         The strategy for hard link introduces a side effect that
  1298.         may or may not be acceptable. Here is the sequence
  1299.     
  1300.         mkdir subdir1
  1301.         touch subdir1/file
  1302.         mkdir subdir2
  1303.         ln    subdir1/file subdir2/file
  1304.         rm    subdir1/file
  1305.         rmdir subdir1
  1306.         rmdir: subdir1: Directory not empty
  1307.     
  1308.         This happen because there is an invisible file (--link) in
  1309.         subdir1 which is referenced by subdir2/file.
  1310.     
  1311.         Any idea ?
  1312.     
  1313.         [linux/fs/umsdos/namei.c,522]
  1314.         #Specification: weakness / hard link / rename directory
  1315.     
  1316.         Another weakness of hard link come from the fact that
  1317.         it is based on hidden symbolic links. Here is an example.
  1318.     
  1319.         mkdir /subdir1
  1320.         touch /subdir1/file
  1321.         mkdir /subdir2
  1322.         ln    /subdir1/file subdir2/file
  1323.         mv    /subdir1 subdir3
  1324.         ls -l /subdir2/file
  1325.     
  1326.         Since /subdir2/file is a hidden symbolic link
  1327.         to /subdir1/..hlinkNNN, accessing it will fail since
  1328.         /subdir1 does not exist anymore (has been renamed).
  1329.     
  1330.         [linux/fs/umsdos/namei.c,980]
  1331.         #Specification: weakness / rename
  1332.     
  1333.         There is a case where UMSDOS rename has a different behavior
  1334.  
  1335.  
  1336.                                                             21
  1337.  
  1338.  
  1339.         than normal UNIX file system. Renaming an open file across
  1340.         directory boundary does not work. Renaming an open file within
  1341.         a directory does work however.
  1342.     
  1343.         The problem (not sure) is in the linux VFS msdos driver.
  1344.         I believe this is not a bug but a design feature, because
  1345.         an inode number represent some sort of directory address
  1346.         in the MSDOS directory structure. So moving the file into
  1347.         another directory does not preserve the inode number.
  1348.     
  1349.     
  1350.     15       utilities                                                   
  1351.     
  1352.     Very little has been done here. Not much is missing though. 
  1353.     Look in the directory umsdos_progs.
  1354.     
  1355.     15.1     The UMSDOS synchroniser                                     
  1356.     
  1357.     
  1358.         [umsdos_progs/util/umssync.c,1]
  1359.         #Specification: utility / synchroniser
  1360.     
  1361.         The UMSDOS synchroniser (umssync) make sure that the EMD file
  1362.         is in sync with the MSDOS directory. File created during a DOS
  1363.         session should be add to the EMD. File removed should erased
  1364.         from the EMD.
  1365.     
  1366.         The UMSDOS file system will operate normally even if the
  1367.         system is out of sync. However, files will be missing from
  1368.         directory search, creating an annoying feeling.
  1369.     
  1370.         There is no easy way this kind of update may be achieved by
  1371.         UMSDOS transparently. Here are the reason:
  1372.     
  1373.         This process take some time for each directory. If there were some
  1374.         access time in MSDOS for directories, then, based on boot time, it would
  1375.         be possible to do it once per directory. It is not the case.
  1376.     
  1377.         When a file is discover in MSDOS which does not exist in the EMD, we
  1378.         need some directives to properly map the file. At least the owner must
  1379.         be known.
  1380.     
  1381.         A set of ioctl are available (wrapper interface in
  1382.         umsdos_progs/umsdosio.c) to allow independant manipulation of the EMD
  1383.         and the DOS directory.
  1384.     
  1385.         A utility is provided. It should be run from /etc/rc.
  1386.         A man page (umssync.8) describe its options.
  1387.     
  1388.         [umsdos_progs/util/umssync.c,425]
  1389.         #Specification: umssync / default creation mode
  1390.     
  1391.         Unless override with command line option, file
  1392.         and directory created by umssync will be owned
  1393.         by root with mode 755 for directories and mode
  1394.         644 for files.
  1395.  
  1396.  
  1397.                                                             22
  1398.  
  1399.  
  1400.         [umsdos_progs/util/umssync.c,435]
  1401.         #Specification: umssync / depth
  1402.     
  1403.         Normally, umssync won't recurse into directory.
  1404.         Option -r allows for depth control. You may specify
  1405.         how deep you want umssync to work.
  1406.     
  1407.         When recursing into directory, umssync will use
  1408.         the owner and group specified on the command line
  1409.         (see option -g and -u). If option -i+ is specified
  1410.         the specs of the sub-directory itself may be used.
  1411.     
  1412.         umssync won't follow symlinks. And it won't cross mount
  1413.         points.
  1414.     
  1415.         [umsdos_progs/util/umssync.c,85]
  1416.         #Specification: umssync / mangled name
  1417.     
  1418.         If a DOS file is missing from the EMD, it is added. If
  1419.         the file has an extension with the first character
  1420.         being a member of the restricted set for mangling,
  1421.         the operation won't be done. A message will be printed.
  1422.     
  1423.         To synchronise back into the EMD, the file must be renamed.
  1424.         If one try to create a such a file with umsdos, it is
  1425.         automaticly mangled, producing a different file name in DOS.
  1426.     
  1427.         This is always done to avoid the following problem
  1428.     
  1429.         Unix command        MsDOS file name created
  1430.         ============        =======================
  1431.         mkdir DIR           dir.{__
  1432.         mkdir dir.{__       dir.{_1
  1433.         ...
  1434.         mkdir dir.{_1       dir.{10
  1435.     
  1436.         Now, suppose that dir.{__ does not exist in the EMD. dir.{_1
  1437.         do exist in DOS. If we try to create it in Umsdos, this
  1438.         will create a mangled name. Mangling in based on the
  1439.         entry offset in the EMD.
  1440.     
  1441.         So if say dir.{_1 exist in DOS, but not in Umsdos, rename
  1442.         it to anything (dir.111) and synchronise it in the EMD
  1443.         with umssync.
  1444.     
  1445.         [umsdos_progs/util/umssync.c,367]
  1446.         #Specification: umssync / mount point
  1447.     
  1448.         umssync won't cross mount point. It means
  1449.         you must specify each mount point separatly.
  1450.     
  1451.         [umsdos_progs/util/umssync.c,544]
  1452.         #Specification: umssync / user mode
  1453.     
  1454.         To execute umssync, the effective user id must be root.
  1455.         It it possible to configure umssync to run setuid root.
  1456.         In this case (when getuid() != geteuid()), umssync
  1457.         show a special behavior: Options -d -f -g -i -u are not
  1458.  
  1459.  
  1460.                                                             23
  1461.  
  1462.  
  1463.         available anymore. The inheriting mode is automaticly
  1464.         activated. No way to desactivated.
  1465.     
  1466.         A user should be able to umssync its own directory. If a user
  1467.         apply umssync to a directory, all file uncovered will be given
  1468.         to the owner of the directory with restrictive permissions
  1469.         (600 for files, 700 for directory).
  1470.     
  1471.         Another way would be to limit umssync operation to directory
  1472.         which belong to the user. Suggestion welcome.
  1473.     
  1474.     
  1475.     15.2     Other                                                       
  1476.     
  1477.     
  1478.         [umsdos_progs/util/udump.c,4]
  1479.         #Specification: utilities / udump
  1480.     
  1481.         udump display the content of a --linux-.--- file (EMD file).
  1482.         Simply type:
  1483.     
  1484.         udump file
  1485.     
  1486.         This utility was mainly used to debug the UMSDOS file systems.
  1487.     
  1488.         [umsdos_progs/util/udosctl.c,12]
  1489.         #Specification: umsdos_progs / udosctl
  1490.     
  1491.         The udosctl utility give acces directly to UMSDOS ioctl on directory.
  1492.     
  1493.         udosctl command arg
  1494.     
  1495.         Here are the commands:
  1496.     
  1497.         ls:
  1498.     
  1499.             List the content of dos directory arg. Bypass the EMD file.
  1500.             It uses UMSDOS_READDIR_DOS.
  1501.     
  1502.         create:
  1503.     
  1504.             Create the file arg in the EMD file. Do nothing on the DOS
  1505.             directory. Use UMSDOS_CREAT_UMSDOS.
  1506.     
  1507.         mkdir:
  1508.     
  1509.             Create the directory arg in the EMD file. Do nothing on the DOS
  1510.             directory. Use UMSDOS_CREAT_UMSDOS.
  1511.     
  1512.         rm:
  1513.     
  1514.             Remove the file arg in the DOS directory. Bypass the EMD file.
  1515.             Use UMSDOS_UNLINK_DOS.
  1516.     
  1517.         rmdir:
  1518.     
  1519.             Remove the directory arg in the DOS directory. Bypass the EMD file.
  1520.  
  1521.  
  1522.                                                             24
  1523.  
  1524.  
  1525.             Use UMSDOS_RMDIR_DOS.
  1526.     
  1527.         uls:
  1528.     
  1529.             List the content of the EMD and print the corresponding DOS
  1530.             mangled name. It uses UMSDOS_READDIR_EMD.
  1531.     
  1532.         urm:
  1533.     
  1534.             Remove the file arg from the EMD file. Don't touch the DOS
  1535.             directory. Use UMSDOS_UNLINK_UMSDOS.
  1536.     
  1537.         urmdir:
  1538.     
  1539.             Remove the directory arg from the EMD file. Don't touch the DOS
  1540.             directory. Use UMSDOS_UNLINK_UMSDOS.
  1541.     
  1542.         version:
  1543.     
  1544.             Prints the version of the UMSDOS driver running.
  1545.     
  1546.         This program was done mostly for illustration of ioctl use
  1547.         and testing.
  1548.     
  1549.     
  1550.     16       Test cases                                                  
  1551.     
  1552.     The umsdos_progs/tests directory holds two utilities. 
  1553.     utstgen is a general test suite "UMSDOS independant". It 
  1554.     tests the general behavior of UMSDOS as a true UNIX-like 
  1555.     file system. utstspc is truely UMSDOS oriented. It (will) 
  1556.     tests the proper behavior of UMSDOS especially when the EMD 
  1557.     and the MSDOS directory are out of sync. Currently utstspc 
  1558.     is not testing much!
  1559.     
  1560.     16.1     utstgen                                                     
  1561.     
  1562.     
  1563.         [umsdos_progs/tests/utstgen.c,7]
  1564.         #Specification: umsdos / automated test / general
  1565.     
  1566.         utstgen.c is a sequence of test for the UMSDOS file system.
  1567.         These test are not really specific to the UMSDOS file system.
  1568.         You will find extensive testing of some stuff which are specific
  1569.         to the UMSDOS file system. There is a long section on hard link
  1570.         which could hardly fail on a normal UNIX file system and were
  1571.         a nightmare to implement in UMSDOS.
  1572.     
  1573.         [umsdos_progs/tests/gen/hlink.c,108]
  1574.         #Specification: utstgen / hard link / cases / across directory boundary
  1575.     
  1576.         The target of the link is not in the same directory
  1577.         as the new link.
  1578.     
  1579.         [umsdos_progs/tests/gen/hlink.c,121]
  1580.         #Specification: utstgen / hard link / cases / target does not exist
  1581.  
  1582.  
  1583.                                                             25
  1584.  
  1585.  
  1586.         Many hard links are attempted to a file which
  1587.         does not exist.
  1588.     
  1589.         [umsdos_progs/tests/gen/hlink.c,127]
  1590.         #Specification: utstgen / hard link / to a directory
  1591.     
  1592.         A hard link can't be made to a directory.
  1593.     
  1594.         [umsdos_progs/tests/gen/hlink.c,50]
  1595.         #Specification: utstgen / hard links / case / link 2 link 2 link ...
  1596.     
  1597.         hlink_simple does test a link made to a link made to a link
  1598.         and so on. On a normal UNIX file system, this test is not
  1599.         really an issue. Given the fact that a hardlink on UMSDOS is
  1600.         a symlink to a hidden file, it make sense to test at least
  1601.         the two cases:
  1602.     
  1603.         hard link to an existing file with no link
  1604.         hard link to an existing file with more than one link.
  1605.     
  1606.         [umsdos_progs/tests/gen/multi.c,67]
  1607.         #Specification: utstgen / multi task / basic test
  1608.     
  1609.         A simple test is performed on a directory, by many task.
  1610.         Only one task must succeeded at a time. The others must fail
  1611.         with specific error code.
  1612.     
  1613.         So we fork 10 time.
  1614.     
  1615.         This test hopes it is a sufficient test :-(
  1616.     
  1617.         [umsdos_progs/tests/gen/file.c,176]
  1618.         #Specification: utstgen / Rename test
  1619.     
  1620.         Rename test are done with files and directories.
  1621.         The following case are tested
  1622.     
  1623.         -In the same directory
  1624.         -In the root directory
  1625.         -In two independant directory
  1626.         -In a subdirectory and the parent
  1627.     
  1628.         The same test is also done on an open file.
  1629.     
  1630.         [umsdos_progs/tests/gen/file.c,199]
  1631.         #Specification: utstgen / Rename test / open file
  1632.     
  1633.         Rename test is done on an open file. We do the following
  1634.         sequence.
  1635.     
  1636.         create a file
  1637.         Open it
  1638.         Rename it
  1639.         Write to the open handle
  1640.         Close it
  1641.         Open the file using the news name
  1642.         Read back the data and check it.
  1643.     
  1644.  
  1645.  
  1646.                                                             26
  1647.  
  1648.  
  1649.         This test does not succeed if the file is renamed accross
  1650.         directories. This sounds like a limitation of the linux msdos
  1651.         driver. I am not sure at this point. I hope it is not
  1652.         a critical feature of a Unix file system. Comments are welcome
  1653.         about this topics. Comments with solution also :-)
  1654.     
  1655.         [umsdos_progs/tests/gen/rename.c,104]
  1656.         #Specification: utstgen / rename / destination exist
  1657.     
  1658.         The following rename tests are done. The source is
  1659.         always file1 and the destination file2 always exist.
  1660.         file2 is a file or a directory. Here a the different
  1661.         case.
  1662.     
  1663.         file1 is a file, file2 is a file.
  1664.         file1 is a file, file2 is a hard link to a file.
  1665.         file1 is a file, file2 exist and is a empty directory.
  1666.         file1 is a file, file2 exist and is a non empty directory.
  1667.     
  1668.         file1 is a directory, file2 is a file.
  1669.         file1 is a directory, file2 is a hard link to a file.
  1670.         file1 is a directory, file2 exist and is a empty directory.
  1671.         file1 is a directory, file2 exist and is a non empty directory.
  1672.     
  1673.         This sequence is performed in the same directory and accros.
  1674.         The following combination are tested.
  1675.     
  1676.         path/dir1   -> path/dir1
  1677.         path/dir1   -> path/dir2
  1678.         path/dir1   -> path
  1679.         path        -> path/dir1
  1680.     
  1681.         [umsdos_progs/tests/gen/syml.c,49]
  1682.         #Specification: utstgen / symbolic links / link 2 link 2 link ...
  1683.     
  1684.         syml_simple does test the number of connected symlink the
  1685.         kernel can handle (A symlink pointing to another pointing
  1686.         to another ... and finally pointing to something.
  1687.     
  1688.         [umsdos_progs/tests/gen/dir.c,142]
  1689.         #Specification: utstgen / creating . and ..
  1690.     
  1691.         A check is done that the special entries . and .. can't be
  1692.         created nor removed.
  1693.     
  1694.         [umsdos_progs/tests/gen/dir.c,160]
  1695.         #Specification: utstgen / removing a busy directory
  1696.     
  1697.         A check is done that a busy directory can't be removed.
  1698.         Here is the sequence we test. It must fail with EBUSY.
  1699.     
  1700.         mkdir dir
  1701.         cd dir
  1702.         rm ../dir
  1703.     
  1704.     
  1705.     16.2     utstspc                                                     
  1706.  
  1707.  
  1708.                                                             27
  1709.  
  1710.  
  1711.     
  1712.         [umsdos_progs/tests/utstspc.c,27]
  1713.         #Specification: umsdos / automated test / specific
  1714.     
  1715.         utstspc.c is a sequence of test for the UMSDOS file system.
  1716.         These tests are specific to the UMSDOS file system.
  1717.     
  1718.         [umsdos_progs/tests/utstspc.c,38]
  1719.         #Specification: utstspc / default environnement
  1720.     
  1721.         utstspc needs to start from a fresh partition (it reformats it).
  1722.         So we normally use it on a floppy. utstspc do mount and umount
  1723.         of that floppy. The default mount point is /mnt and the default
  1724.         drive (for mformat) is F:.
  1725.     
  1726.         This value F: looks very odd. This comes from my own setup.
  1727.         Here is my definition for /etc/mtools
  1728.     
  1729.         A /dev/fd0 12 0 0 0
  1730.         B /dev/fd1 12 0 0 0
  1731.         E /dev/fd0h1200 12 80 2 15  # A: 5 1/4
  1732.         F /dev/fd1H1440 12 80 2 18  # B: 3 1/2
  1733.     
  1734.         Using /dev/fd0 and /dev/fd1 on A and B, this gives me flexibility
  1735.         for normal operation. I can read any type of floppy without much
  1736.         question. I can't do a mformat A: or B:. I always get an error.
  1737.         I guess /dev/fd0 are flexible driver, so do not impose a format.
  1738.     
  1739.         The entries E and F replicate A and B but this time use the specific
  1740.         device. So  I can do a "mformat f:" and expect to format a 1.44
  1741.         3 1/2 floppy correctly.
  1742.     
  1743.         Of course if you know better, please tell me!
  1744.     
  1745.         [umsdos_progs/tests/utstspc.c,129]
  1746.         #Specification: utstspc / floppy only
  1747.     
  1748.         To avoid desaster, utstspc will only work on floppy.
  1749.         A test is done before everything to ensure that
  1750.         the drive is indeed a floppy.
  1751.     
  1752.         It use /etc/mtools to locate the proper device. It also
  1753.         assume a floppy device have a path starting with
  1754.         "/dev/fd". This is not fool proof!
  1755.     
  1756.         [umsdos_progs/tests/utilspc.c,86]
  1757.         #Specification: utstspc / what's needed
  1758.     
  1759.         utstspc use different other program to achieve its test.
  1760.         It has to reformat, mount, unmount etc... the floppy
  1761.         on which it is doing the test.
  1762.     
  1763.         utstspc assume that the following utility are available.
  1764.     
  1765.         /usr/bin/mformat
  1766.         /etc/mount or /bin/mount
  1767.         /etc/umount or /bin/umount
  1768.     
  1769.  
  1770.  
  1771.                                                             28
  1772.  
  1773.  
  1774.         Also, it requieres /etc/mtools
  1775.     
  1776.         [umsdos_progs/tests/spc/hlink.c,119]
  1777.         #Specification: utstspc / hard link / cases / across directory boundary
  1778.     
  1779.         The target of the link is not in the same directory
  1780.         as the new link.
  1781.     
  1782.         [umsdos_progs/tests/spc/hlink.c,144]
  1783.         #Specification: utstspc / hard link / cases / target does not exist
  1784.     
  1785.         Many hard links are attempted to a file which
  1786.         does not exist.
  1787.     
  1788.         [umsdos_progs/tests/spc/hlink.c,134]
  1789.         #Specification: utstspc / hard link / in a DOS directory
  1790.     
  1791.         A test is done to demonstrate that a hard link can't be
  1792.         created in a DOS directory.
  1793.     
  1794.         [umsdos_progs/tests/spc/hlink.c,100]
  1795.         #Specification: utstspc / hard link / subdirectory of a dos directory
  1796.     
  1797.         We create two subdirectory in a DOS directory. We switch
  1798.         those to Umsdos mode (umssync). We set a lot of hard link
  1799.         between those two directories.
  1800.     
  1801.         This test try to demonstrate that the only thing that
  1802.         matter is that both subdirectory must be umsdos directories.
  1803.         But the parents don't have to.
  1804.     
  1805.         [umsdos_progs/tests/spc/hlink.c,150]
  1806.         #Specification: utstspc / hard link / to a directory
  1807.     
  1808.         A hard link can't be made to a directory.
  1809.     
  1810.         [umsdos_progs/tests/spc/hlink.c,50]
  1811.         #Specification: utstspc / hard links / case / link 2 link 2 link ...
  1812.     
  1813.         hlink_simple does test a link made to a link made to a link
  1814.         and so on. On a normal UNIX file system, this test is not
  1815.         really an issue. Given the fact that a hardlink on UMSDOS is
  1816.         a symlink to a hidden file, it make sense to test at least
  1817.         the two cases:
  1818.     
  1819.         hard link to an existing file with no link
  1820.         hard link to an existing file with more than one link.
  1821.     
  1822.         [umsdos_progs/tests/spc/read.c,109]
  1823.         #Specification: utstspc / read write
  1824.     
  1825.         We write files with special pattern and read it back
  1826.         using different blocking scheme. This is to make sure
  1827.         the new read ahead support in the msdos fs is not screwing.
  1828.     
  1829.         [umsdos_progs/tests/spc/read.c,152]
  1830.         #Specification: utstspc / read write / text mode
  1831.     
  1832.  
  1833.  
  1834.                                                             29
  1835.  
  1836.  
  1837.         The read/write test is done is text conversion mode also.
  1838.         This prove the read ahead of fs/msdos/file.c is working
  1839.         even in conv=text mode.
  1840.     
  1841.     
  1842.     
  1843.     17       The MsDOS fs                                                
  1844.     
  1845.     Umsdos runs piggy back on top of the MsDOS fs of linux. 
  1846.     Umsdos could be reusable to play the same game on top of 
  1847.     another fs (hpfs) but there is different small quirk msdos 
  1848.     specific in it. And off course it calls few msdos fs 
  1849.     function directly. We will present some specs of the msdos 
  1850.     fs here. It is not that much related to the design of Umsdos 
  1851.     but it might be one day.
  1852.     
  1853.     
  1854.         [linux/fs/msdos/buffer.c,20]
  1855.         #Specification: msdos / strategy / special device / dummy blocks
  1856.     
  1857.         Many special device (Scsi optical disk for one) use
  1858.         larger hardware sector size. This allows for higher
  1859.         capacity.
  1860.     
  1861.         Most of the time, the MsDOS file system that sit
  1862.         on this device is totally unaligned. It use logically
  1863.         512 bytes sector size, with logical sector starting
  1864.         in the middle of a hardware block. The bad news is
  1865.         that a hardware sector may hold data own by two
  1866.         different files. This means that the hardware sector
  1867.         must be read, patch and written allmost all the time.
  1868.     
  1869.         Needless to say that it kills write performance
  1870.         on all OS.
  1871.     
  1872.         Internally the linux msdos fs is using 512 bytes
  1873.         logical sector. When accessing such a device, we
  1874.         allocate dummy buffer cache blocks, that we stuff
  1875.         with the information of a real one (1k large).
  1876.     
  1877.         This strategy is used to hide this difference to
  1878.         the core of the msdos fs. The slowdown is not
  1879.         hidden though!
  1880.     
  1881.         [linux/fs/msdos/file.c,60]
  1882.         #Specification: msdos / special devices / mmap
  1883.     
  1884.         Mmapping does work because a special mmap is provide in that case.
  1885.         Note that it is much less efficient than the generic_mmap normally
  1886.         used since it allocate extra buffer. generic_mmap is used for
  1887.         normal device (512 bytes hardware sectors).
  1888.     
  1889.         [linux/fs/msdos/file.c,79]
  1890.         #Specification: msdos / special devices / swap file
  1891.     
  1892.         Swap file can't work on special devices with a large sector
  1893.         size (1024 bytes hard sector). Those devices have a weird
  1894.  
  1895.  
  1896.                                                             30
  1897.  
  1898.  
  1899.         MsDOS filesystem layout. Generally a single hardware sector
  1900.         may contain 2 unrelated logical sector. This mean that there is
  1901.         no easy way to do a mapping between disk sector of a file and virtual
  1902.         memory. So swap file is difficult (not available right now)
  1903.         on those devices. Off course, Ext2 does not have this problem.
  1904.     
  1905.         [linux/fs/msdos/buffer.c,68]
  1906.         #Specification: msdos / special device / writing
  1907.     
  1908.         A write is always preceded by a read of the complete block
  1909.         (large hardware sector size). This defeat write performance.
  1910.         There is a possibility to optimize this when writing large
  1911.         chunk by making sure we are filling large block. Volunter ?
  1912.     
  1913.     
  1914.